<?php

	require_once 'BaseObject.class.php';
	require_once 'PeerObject.class.php';
	require_once 'UseObject.class.php';
	require_once 'ModelObject.class.php';
	require_once 'ModelPeerObject.class.php';
	require_once 'ServiceObject.class.php';
	require_once 'ServiceProxyObject.class.php';
	require_once 'SqlCreate.class.php';
	require_once CORMO_DIR_CORE.'Schema.class.php';
	require_once CORMO_DIR_CORE.'File.class.php';
	
	/**
	 * A partir de la configuracio en schema.php creara las Class necesarias para 
	 * poder manejar las persistencia de cada una de la tablas que se han definido 
	 * para el sistema.
	 *
   * @category cormo
   * @package Generator
   * @author Germán Dario Peraferrer <gperaferrer@gmail.com>
   * @copyright Copyright (c) 2007 Germán Dario Peraferrer - Beetec
   * @version 1.0 Beta
   * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
   * @link http://code.google.com/p/cormoframework/
   * @link http://www.beetec.com.ar
	 */
	class Generator	{
		/**
		 * Se almacenan las Tablas que se crearan como Objeto.
		 *
		 * @var array
		 */
		private $objects;
		
		/**
		 * Se almacenan los Web Services de los cuales se crearan Class Proxy
		 *
		 * @var array
		 */
		private $wsdlObjects;

		/**
		 * Objeto Temporal para la creacion del nuevo Base<ObjetORM>
		 *
		 * @var BaseObject
		 */
		private $BaseObject;
		
		/**
		 * Objeto Temporal para la creacion del nuevo Peer<ObjetORM>
		 *
		 * @var PeerObject
		 */
		private $PeerObject;
		
		/**
		 * Objeto Temporal para la creacion del nuevo Use<ObjetORM>
		 *
		 * @var UseObject
		 */
		private $UseObject;
		
		/**
		 * Objeto Temporal para la creacion del nuevo Modelo final para el <ObjectORM>
		 *
		 * @var ModelObject
		 */
		private $ModelObject;
		
		/**
		 * Objeto Temporal para la creacion del nuevo Qry<ObjectORM>
		 *
		 * @var ModelPeerObject
		 */
		private $ModelPeerObject;
		
		/**
		 * Objeto Temporal para la creacion del nuevo wsdl<ObjectORM>
		 *
		 * @var ServiceObject
		 */
		private $ServiceObject;
		
		/**
		 * Objeto Temporal para la creaci�n del nuevo proxy<ProxyNameObject>
		 *
		 * @var servicePrxyObject
		 */
		private $ServiceProxyObject;
		
		/**
		 * Objeo Temporal para la creaci�n de la Sentencia SQL CREATE
		 */
		private $sqlCreate;
		
		/**
		 * Contenido temporal que luego formara el archivo autoLoad.php, encargado de cargar los Class invocados autom�ticamente.
		 *
		 * @var string
		 */
		private $autoLoad;
		
		public function __construct() {
			global $CORMO;
			$arrObjects = array();
			$arrWsdlObjects = array();
			
			// Controlamos is existe la configuracion
			if (isset($CORMO))	{

				// Verificamos si posee algun dato
				if (count($CORMO) > 1)	{

					/**
					 * Buscamos las Tabals de las que se deben crear Class
					 */

					// Recorremos la configuracion para determinar los objetos a crear
					foreach($CORMO as $object => $cfg)	{
						// Filtramos solos los Array que representan Object / Table
						if (substr($object, 0, 4) === 'orm_')
							array_push($arrObjects, $cfg["ObjectName"]);

						// Filtramos solos los Array que representan WSDL / Class Proxy
						if (substr($object, 0, 5) === 'wsdl_')
							array_push($arrWsdlObjects, $cfg["ObjectName"]);
					}

					$this->setObjects($arrObjects);
					$this->setWsdlObjects($arrWsdlObjects);
					
				}	else	{
					echo "La configuracion para el ORM se encuentra incompleta.";
				}
		
			} else {
				echo "No existe la configuracion para iniciar el ORM.";		
			}
			
		}
		
		public function generate($path, $createSQL = true) {

			// Verificamos si Schema es valido
			if (!Schema::isValidSchema(&$logValidate)) {
				echo $logValidate;
			} else {
				if (is_dir($path))	{
					if ($gDir = opendir($path))	{

						// Definimos el encabezado del archivo autoLoad.php
						$this->autoLoad .= '  /**'."\n";
						$this->autoLoad .= '   * File generado automáticamente cormo.'."\n";
						$this->autoLoad .= '   * '."\n";
						$this->autoLoad .= '   * @category cormo'."\n";
						$this->autoLoad .= '   * @package Config'."\n";
						$this->autoLoad .= '   * @author Germán Dario Peraferrer <gperaferrer@gmail.com>'."\n";
						$this->autoLoad .= '   * @copyright Copyright (c) 2007 Germán Dario Peraferrer - Beetec'."\n";
						$this->autoLoad .= '   * @version 1.0 Beta'."\n";
						$this->autoLoad .= '   * @license http://www.opensource.org/licenses/bsd-license.php New BSD License'."\n";
						$this->autoLoad .= '   * @link http://code.google.com/p/cormoframework/'."\n";
						$this->autoLoad .= '   * @link http://www.beetec.com.ar'."\n";
						$this->autoLoad .= '   */'."\n";
						$this->autoLoad .= "\n";
						$this->autoLoad .= '  function __autoload($className) {'."\n";
						$this->autoLoad .= '		global $CORMO;'."\n\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Access.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Connection.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'DriverAccess.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Message.class.php';"."\n";
						$this->autoLoad .= "    require_once CORMO_DIR_CORE.'Object.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Peer.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Peer.interface.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Persist.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Persist.interface.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Schema.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'WebServices.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Cormo.class.php';"."\n";
						$this->autoLoad .= "		require_once CORMO_DIR_CORE.'Debug.class.php';"."\n\n";
						$this->autoLoad .= '		if (CORMO_AUTO_LOAD_CLASS) {'."\n";
						$this->autoLoad .= '		  switch ($className) {'."\n";
					
						closedir($gDir);					

						// Eliminamos las Carpetas en donde vamos a almacenar las Class Creadas
						File::removeFolder($path.'model/');
						File::removeFolder($path.'controller/');
						File::removeFolder($path.'sql/');
						@unlink($path.'autoLoad.php');
					
						// Creamos los Directorios Nuevamente
						mkdir($path.'model/');					
						mkdir($path.'model/peer');		
						mkdir($path.'model/base/');					
						mkdir($path.'model/base/peer/');					
						mkdir($path.'model/use/');					
						mkdir($path.'controller/');
						mkdir($path.'controller/service');
						mkdir($path.'controller/serviceProxy');

						// Verificamos si debemos crear los SQL
						if ($createSQL) {
							mkdir($path.'sql/');
						}					
					
						echo '<HTML><HEAD><TITLE>cormo v'.CORMO_VERSION.' - Generator Class</TITLE></HEAD><body>';
						echo '<A name="arriba"></A>';
						echo '<h1>cormo v'.CORMO_VERSION.' - Generator</h1>';
						echo "Class que ser�n generadas para cada una de las entidades definidas en phpORM/Core/schema.php.<br>";
						echo 'Haciendo clic en cada nombre de class podr� visualizar el code que se ha generado.<br>';
						echo "<b>Recuerde:</b> en la carpeta ".CORMO_DIR_GENERATOR_BUILDER." se localir� el codigo generado, que aqu� se aprecia.<br>";
						echo '<hr>';

						// Objetos que seran creados
						foreach($this->getObjects() as $object)	{
							echo '<ul><b> Object: '.$object.'</b>';
							echo '<li><A href="#Base'.$object.'.class.php">'.'Base'.$object.'</A></li>';
							echo '<ul><li><A href="#Use'.$object.'.class.php">'.'Use'.$object.'</A></li>';
							echo '<ul><li><A href="#'.$object.'.class.php">'.$object.'</A></li></ul></ul>';
							echo '<li><A href="#Peer'.$object.'.class.php">'.'Peer'.$object.'</A></li>';
							echo '<ul><li><A href="#Qry'.$object.'.class.php">'.'Qry'.$object.'</A></li></ul>';
							echo '<li><A href="#'.$object.'.wsdl.php">'.$object.'.wsdl</li></A>';
							echo '</ul>----------------------------------------';
						}
					
						echo "<hr>";
					
						echo '<b>Class Proxy para Web Services Externos:</b><br>';
						echo 'Class Proxy que se encargan de llamar los diferentes metodos de los Web Services que hemos definido en el Schema.<br>';
						echo 'Las mismas le permitiran utilizar los Web Services como se se tratase de otro Object m�s.<br>';

						echo "<hr>";
					
						// Objetos Web Services Proxy que seran creados
						foreach($this->getWsdlObjects() as $wsdlObject)	{
							echo '<A href="#proxy'.$wsdlObject.'.class.php">'.'proxy'.$wsdlObject.'</A><br>';
						}
					
						echo "<br><hr>";

						// Verificamos si debemos crear los SQL
						if ($createSQL) {
							echo '<b>SQL CREATE:</b><br>';
							echo 'Archivos con la sentencia SQL que nos facilita la creaci�n de la Tabla en la Base de Datos.<br>';

							echo "<hr>";
					
							// Objetos que seran creados
							foreach($this->getObjects() as $object)	{
								echo '<A href="#'.$object.'.sql">'.$object.'.sql</A><br>';
							}
										
							echo "<br><hr>";
						
						}
					
					
						/**
						 * Tratar los Class / Table
						 */
					
						// Recorremos las Tablas de las cuales debemos crear las Class Respectivas
						foreach($this->getObjects() as $object)	{
				
							// Creamos la Class BASE de la Tabla / Class
							$this->setBaseObject(new BaseObject('orm_'.$object));
							File::createFile($path.'model/base/Base'.$object.'.class.php', '<?php'."\n\n".$this->BaseObject."\n".'?>');
							$this->autoLoad .= "			  case 'Base".$object."':"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_BASE.'Base".$object.".class.php';"."\n";
							$this->autoLoad .= "			    break;"."\n";
						
							// Creamos la Class USE de la Tabla / Class
							$this->setUseObject(new UseObject('orm_'.$object));
							File::createFile($path.'model/use/Use'.$object.'.class.php', '<?php'."\n\n".$this->UseObject."\n".'?>');
							$this->autoLoad .= "			  case 'Use".$object."':"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_USE.'Use".$object.".class.php';"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_BASE.'Base".$object.".class.php';"."\n";
							$this->autoLoad .= "			    break;"."\n";
						
							// Creamos la Class MODEL de la Tabla / Class
							$this->setModelObject(new ModelObject('orm_'.$object));
							File::createFile($path.'model/'.$object.'.class.php', '<?php'."\n\n".$this->ModelObject."\n".'?>');
							$this->autoLoad .= "	  		case '".$object."':"."\n";
							$this->autoLoad .= "		  	    require_once CORMO_DIR_MODEL.'".$object.".class.php';"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_USE.'Use".$object.".class.php';"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_BASE.'Base".$object.".class.php';"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_BASE_PEER.'Peer".$object.".class.php';"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_MODEL_QRY.'Qry".$object.".class.php';"."\n";
							$this->autoLoad .= "			    break;"."\n";
						
							// Creamos la Class PEER de la Tabla / Class
							$this->setPeerObject(new PeerObject('orm_'.$object));
							File::createFile($path.'model/Base/Peer/Peer'.$object.'.class.php', '<?php'."\n\n".$this->PeerObject."\n".'?>');
							$this->autoLoad .= "			  case 'Peer".$object."':"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_BASE_PEER.'Peer".$object.".class.php';"."\n";
							$this->autoLoad .= "			    break;"."\n";
						
							// Creamos la Class MODEL PEER de la Tabla / Class
							$this->setModelPeerObject(new ModelPeerObject('orm_'.$object));
							File::createFile($path.'model/peer/Qry'.$object.'.class.php', '<?php'."\n\n".$this->ModelPeerObject."\n".'?>');
							$this->autoLoad .= "			  case 'Qry".$object."':"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_MODEL_QRY.'Qry".$object.".class.php';"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_BASE_PEER.'Peer".$object.".class.php';"."\n";
							$this->autoLoad .= "			    break;"."\n";
						
							// Creamos la Class WSDL de la Tabla / Class
							$this->setServiceObject(new ServiceObject('orm_'.$object));
							File::createFile($path.'controller/service/'.$object.'.wsdl.php', '<?php'."\n\n".$this->ServiceObject."\n".'?>');

							echo "<pre>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="Base'.$object.'.class.php">'.$path.'model/base/Base'.$object.'.class.php'.'</A><br>';
							show_source($path.'model/base/Base'.$object.'.class.php');
							echo "<hr>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="Use'.$object.'.class.php">'.$path.'model/use/Use'.$object.'.class.php'.'</A><br>';
							show_source($path.'model/use/Use'.$object.'.class.php');
							echo "<hr>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="'.$object.'.class.php">'.$path.'model/'.$object.'.class.php'.'</A><br>';
							show_source($path.'model/'.$object.'.class.php');
							echo "<hr>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="Peer'.$object.'.class.php">'.$path.'model/base/peer/Peer'.$object.'.class.php'.'</A><br>';
							show_source($path.'model/base/peer/Peer'.$object.'.class.php');
							echo "<hr>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="Qry'.$object.'.class.php">'.$path.'model/peer/Qry'.$object.'.class.php'.'</A><br>';
							show_source($path.'model/peer/Qry'.$object.'.class.php');
							echo "<hr>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="'.$object.'.wsdl.php">'.$path.'controller/service/'.$object.'.wsdl.php'.'</A><br>';
							show_source($path.'controller/service/'.$object.'.wsdl.php');
							echo "</pre>";
							echo "<hr>";
						
							// Destruimos los Objetos para crearlos nuevamente en el ciclo
							$this->BaseObject = null;
							$this->UseObject = null;
							$this->ModelObject = null;
							$this->PeerObject = null;
							$this->ModelPeerObject = null;
							$this->ServiceObject = null;
				
						}

						/**
						 * Tratar los Web Service / Class Proxy
						 */
					
						// Recorremos los Web Services de las cuales debemos crear las Class Proxy Respectivas
						foreach($this->getWsdlObjects() as $object)	{
				
							// Creamos la Class WSDL de la Tabla / Class
							$this->setServiceProxyObject(new ServiceProxyObject('wsdl_'.$object));
							File::createFile($path.'controller/serviceProxy/proxy'.$object.'.class.php', '<?php'."\n\n".$this->ServiceProxyObject."\n".'?>');
							$this->autoLoad .= "			  case 'proxy".$object."':"."\n";
							$this->autoLoad .= "			      require_once CORMO_DIR_SERVICE_PROXY.'proxy".$object.".class.php';"."\n";
							$this->autoLoad .= "			    break;"."\n";
							
							echo "<pre>";
							echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="proxy'.$object.'.class.php">'.$path.'controller/serviceProxy/proxy'.$object.'.class.php'.'</A><br>';
							show_source($path.'controller/serviceProxy/proxy'.$object.'.class.php');
							echo "</pre>";
							echo "<hr>";
						
							echo '</body></HTML>';

							// Destruimos los Objetos para crearlos nuevamente en el ciclo
							$this->ServiceProxyObject = null;
				
						}
					
						/**
						 * Tratar los SQL CREATE
						 */
					
						// Verificamos si debemos crear los SQL
						if ($createSQL) {
							// Recorremos las Tablas de las cuales debemos crear las Class Respectivas
							foreach($this->getObjects() as $object)	{
								// Creamos el Archivo SQL CREATE
								$this->setSqlCreate(new SqlCreate('orm_'.$object));
								File::createFile($path.'SQL/'.$object.'.sql', $this->sqlCreate);
						
								echo "<pre>";
								echo '<A href="#arriba">Volver Arriba</A> - Archivo: <A name="'.$object.'.sql">'.$path.'sql/'.$object.'.sql'.'</A><br>';
								show_source($path.'sql/'.$object.'.sql');
								echo "</pre>";
								echo "<hr>";
						
								echo '</body></HTML>';

								// Destruimos los Objetos para crearlos nuevamente en el ciclo
								$this->sqlCreate = null;
				
							}
						}
					
						/**
						 * Creamos el archivo autoLoad.php
						 */
					
						$this->autoLoad .= '		  }'."\n";
						$this->autoLoad .= '		}'."\n";
						$this->autoLoad .= '	}'."\n";
						File::createFile($path.'autoLoad.php', '<?php'."\n\n".$this->autoLoad."\n".'?>');
					
					}	else	{
    					echo '<h1>cormo v'.CORMO_VERSION.' - Generator Class</h1>';
        				echo '<h3><font color="red">ERROR</font>: No se ha podido abrir el directorio ('.$path.')<br>Verifique config.php en CORMO_DIR_GENERATOR_BUILDER.</h3>';
					}
				
				}	else	{
					echo '<h1>cormo v'.CORMO_VERSION.' - Generator Class</h1>';
					echo '<h3><font color="red">ERROR</font>: No es un Path Valido ('.$path.')<br>Verifique config.php en CORMO_DIR_GENERATOR_BUILDER.</h3>';
				}
			
			}
			
			
		}

		/**
		 * Obtiene el array con las Tablas que seran representadas en Class
		 *
		 * @return array
		 */
		private function getObjects()  {
			return $this->objects;
		}
		
		/**
		 * Define el array de las Tablas que deberan ser representadas en Class
		 *
		 * @param array $objects
		 */
		private function setObjects($objects)  {
			$this->objects = $objects;
		}
		
		/**
		 * Obtiene el array con los Web Services que seran representadas en Class Proxy
		 *
		 * @return array
		 */
		private function getWsdlObjects()  {
			return $this->wsdlObjects;
		}
		
		/**
		 * Define el array de los Web Services que deberan ser representadas en Class Proxy
		 *
		 * @param array $wsdlObjects
		 */
		private function setWsdlObjects($wsdlObjects)  {
			$this->wsdlObjects = $wsdlObjects;
		}
		
		private function getBaseObject() {
			return $this->BaseObject;
		}
		
		private function setBaseObject(BaseObject $baseObject) {
			$this->BaseObject = $baseObject;
		}
		
		private function getPeerObject() {
			return $this->PeerObject;
		}
		
		private function setPeerObject(PeerObject $peerObject) {
			$this->PeerObject = $peerObject;
		}
		
		private function getUseObject() {
			return $this->UseObject;
		}
		
		private function setUseObject(UseObject $useObject) {
			$this->UseObject = $useObject;
		}
		
		private function getModelObject() {
			return $this->ModelObject;
		}
		
		private function setModelObject(ModelObject $modelObject) {
			$this->ModelObject = $modelObject;
		}
		
		private function getModelPeerObject() {
			return $this->ModelPeerObject;
		}
		
		private function setModelPeerObject(ModelPeerObject $modelPeerObject) {
			$this->ModelPeerObject = $modelPeerObject;
		}
		
		private function getServiceObject() {
			return $this->ServiceObject;
		}
		
		private function setServiceObject(ServiceObject $serviceObject) {
			$this->ServiceObject = $serviceObject;
		}
		
		private function getServiceProxyObject() {
			return $this->ServiceProxyObject;
		}
		
		private function setServiceProxyObject(ServiceProxyObject $serviceProxyObject) {
			$this->ServiceProxyObject = $serviceProxyObject;
		}
		
		private function getSqlCreate() {
			return $this->sqlCreate;
		}
		
		private function setSqlCreate(SqlCreate $sqlCreate) {
			$this->sqlCreate = $sqlCreate;
		}
		
	}

?>